package com.zbkj.service.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbkj.common.constants.RedisConstants;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.AiFittingCategory;
import com.zbkj.common.model.UserModelUrl;
import com.zbkj.common.request.LevelMaskRequest;
import com.zbkj.common.request.ProductCategoryRequest;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.result.ProductResultCode;
import com.zbkj.common.utils.RedisUtil;
import com.zbkj.common.vo.ProCategoryCacheTree;
import com.zbkj.common.vo.ProCategoryCacheVo;
import com.zbkj.service.dao.AiFittingCategoryDao;
import com.zbkj.service.service.AiFittingCategoryService;
import com.zbkj.service.service.SystemAttachmentService;
import com.zbkj.service.service.UserModelUrlService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


/**
 * @author keNan
 * @description AiFittingCategoryServiceImpl 接口实现
 * @date 2025-06-04
 */
@Service
public class AiFittingCategoryServiceImpl extends ServiceImpl<AiFittingCategoryDao, AiFittingCategory> implements AiFittingCategoryService {

    @Resource
    private AiFittingCategoryDao dao;
    @Autowired
    private SystemAttachmentService systemAttachmentService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private UserModelUrlService userModelUrlService;


    /**
     * 获取分类列表
     */
    @Override
    public List<AiFittingCategory> getAdminList() {
        LambdaQueryWrapper<AiFittingCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(AiFittingCategory::getIsDel, false);
        lqw.orderByDesc(AiFittingCategory::getSort);
        lqw.orderByAsc(AiFittingCategory::getId);
        return dao.selectList(lqw);
    }

    /**
     * @param request 添加参数
     * @return Boolean
     */
    @Override
    public Boolean add(ProductCategoryRequest request) {
        if (checkName(request.getName(), request.getPid())) {
            throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "分类名称已存在");
        }
        AiFittingCategory aiFittingCategory = new AiFittingCategory();
        BeanUtils.copyProperties(request, aiFittingCategory);
        aiFittingCategory.setId(null);
        aiFittingCategory.setPid(0);
        if (!request.getLevel().equals(1)) {
            if (request.getPid().equals(0)) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "子级菜单，父级ID不能为0");
            }
            AiFittingCategory category = getByIdException(request.getPid());
            if (category.getLevel() >= request.getLevel()) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "新增的商品分类层级异常");
            }
            aiFittingCategory.setPid(request.getPid());
        }
        if (StrUtil.isNotBlank(aiFittingCategory.getIcon())) {
            aiFittingCategory.setIcon(systemAttachmentService.clearPrefix(aiFittingCategory.getIcon()));
        }
        boolean save = save(aiFittingCategory);
        if (save) {
            redisUtil.delete(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY);
            redisUtil.delete(RedisConstants.AI_FITTING_CATEGORY_CACHE_MERCHANT_LIST_KEY);
        }
        return save;
    }

    /**
     * 删除分类
     *
     * @param id 分类ID
     * @return Boolean
     * 删除时，需要判断分类是否被使用
     * 1.是否被品牌关联
     * 2.是否被商品使用
     * 后续改成如果1，2级分类，有子分类时无法删除
     */
    @Override
    public Boolean delete(Integer id) {
        AiFittingCategory category = getByIdException(id);
        if (category.getLevel() < 3) {
            List<AiFittingCategory> categoryList = findAllChildListByPid(category.getId(), category.getLevel());
            if (CollUtil.isNotEmpty(categoryList)) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "请先删除子级分类");
            }
        }
        // 判断是否品牌关联该分类
//        if (productBrandCategoryService.isExistCategory(category.getId())) {
//            throw new CrmebException(ProductResultCode.PRODUCT_PLAT_CATEGORY_USED.setMessage("有品牌关联该分类，无法删除"));
//        }
        category.setIsDel(true);
        Boolean update = transactionTemplate.execute(e -> {
            updateById(category);
            // 删除商品分类相关优惠券
//            couponService.deleteByProCategoryId(category.getId());
            return Boolean.TRUE;
        });
        if (update) {
            redisUtil.delete(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY);
            redisUtil.delete(RedisConstants.AI_FITTING_CATEGORY_CACHE_MERCHANT_LIST_KEY);
        }
        return update;
    }

    /**
     * 修改分类
     *
     * @param request 修改参数
     * @return Boolean
     */
    @Override
    public Boolean edit(ProductCategoryRequest request) {
        if (ObjectUtil.isNull(request.getId()) || ObjectUtil.isNull(request.getPid())) {
            throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品分类ID或Pid不能为空");
        }
        AiFittingCategory oldCategory = getByIdException(request.getId());
        if (!oldCategory.getName().equals(request.getName()) || !oldCategory.getPid().equals(request.getPid())) {
            if (checkName(request.getName(), request.getPid())) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "分类名称已存在");
            }
        }

        AiFittingCategory category = new AiFittingCategory();
        BeanUtils.copyProperties(request, category);
        category.setPid(oldCategory.getPid());
        if (StrUtil.isNotBlank(category.getIcon())) {
            category.setIcon(systemAttachmentService.clearPrefix(category.getIcon()));
        }
        boolean update = updateById(category);
        if (update) {
            redisUtil.delete(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY);
            redisUtil.delete(RedisConstants.AI_FITTING_CATEGORY_CACHE_MERCHANT_LIST_KEY);
        }
        return update;
    }

    /**
     * 修改分类显示状态
     *
     * @param id 分类ID
     * @return Boolean
     */
    @Override
    public Boolean updateShowStatus(Integer id) {
        AiFittingCategory category = getByIdException(id);
        List<AiFittingCategory> categoryList = new ArrayList<>();
        boolean showStatus = !category.getIsShow();
        if (!category.getLevel().equals(1) && showStatus) {
            AiFittingCategory parentCategory = getByIdException(category.getPid());
            if (parentCategory.getIsShow().equals(false)) {
                parentCategory.setIsShow(showStatus);
                categoryList.add(parentCategory);
            }
            if (parentCategory.getLevel().equals(2)) {
                AiFittingCategory firstCategory = getByIdException(parentCategory.getPid());
                if (firstCategory.getIsShow().equals(false)) {
                    firstCategory.setIsShow(showStatus);
                    categoryList.add(firstCategory);
                }
            }
        }

        category.setIsShow(showStatus);
        categoryList.add(category);
        Boolean update = transactionTemplate.execute(e -> {
            updateBatchById(categoryList);
            if (category.getLevel().equals(2)) {
                updateChildShowStatus(category.getId(), showStatus);
            }
            if (category.getLevel().equals(1)) {
                List<AiFittingCategory> productCategoryList = findAllChildListByPid(category.getId(), category.getLevel());
                productCategoryList.forEach(c -> c.setIsShow(showStatus));
                updateBatchById(productCategoryList, 100);
            }
            return Boolean.TRUE;
        });

        if (update) {
            // 平台端缓存列表不受显示状态影响
            redisUtil.delete(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY);
            redisUtil.delete(RedisConstants.AI_FITTING_CATEGORY_CACHE_MERCHANT_LIST_KEY);
        }
        return update;
    }

    /**
     * 更新子级显示状态
     *
     * @param pid 父级ID
     */
    private void updateChildShowStatus(Integer pid, Boolean showStatus) {
        LambdaUpdateWrapper<AiFittingCategory> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(AiFittingCategory::getIsShow, showStatus);
        wrapper.eq(AiFittingCategory::getPid, pid);
        update(wrapper);
    }

    /**
     * 获取分类缓存树
     *
     * @return List<ProCategoryCacheVo>
     */
    @Override
    public List<ProCategoryCacheVo> getCacheTree() {
        List<AiFittingCategory> categoryList = CollUtil.newArrayList();
        if (redisUtil.exists(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY)) {
            categoryList = redisUtil.get(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY);
        } else {
            LambdaQueryWrapper<AiFittingCategory> lqw = Wrappers.lambdaQuery();
            lqw.eq(AiFittingCategory::getIsDel, false);
            categoryList = dao.selectList(lqw);
            if (CollUtil.isEmpty(categoryList)) {
                return CollUtil.newArrayList();
            }
            redisUtil.set(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY, categoryList);
        }
        List<ProCategoryCacheVo> voList = categoryList.stream().map(e -> {
            ProCategoryCacheVo cacheVo = new ProCategoryCacheVo();
            BeanUtils.copyProperties(e, cacheVo);
            return cacheVo;
        }).collect(Collectors.toList());
        ProCategoryCacheTree categoryTree = new ProCategoryCacheTree(voList);
        return categoryTree.buildTree();
    }


    /**
     * 根据菜单id获取所有下级对象
     *
     * @param pid   菜单id
     * @param level 分类级别
     * @return List<ProductCategory>
     */
    @Override
    public List<AiFittingCategory> findAllChildListByPid(Integer pid, Integer level) {
        LambdaQueryWrapper<AiFittingCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(AiFittingCategory::getPid, pid);
        lqw.eq(AiFittingCategory::getIsDel, false);
        if (level.equals(2)) {
            return dao.selectList(lqw);
        }
        // level == 1
        List<AiFittingCategory> categoryList = dao.selectList(lqw);
        if (CollUtil.isEmpty(categoryList)) {
            return categoryList;
        }
        List<Integer> pidList = categoryList.stream().map(AiFittingCategory::getId).collect(Collectors.toList());
        lqw.clear();
        lqw.in(AiFittingCategory::getPid, pidList);
        lqw.eq(AiFittingCategory::getIsDel, false);
        List<AiFittingCategory> childCategoryList = dao.selectList(lqw);
        categoryList.addAll(childCategoryList);
        return categoryList;
    }


    /**
     * 获取一级专题分类列表
     *
     * @return
     */
    @Override
    public List<AiFittingCategory> getFirstSpecialTopicCategory() {
        LambdaQueryWrapper<AiFittingCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(AiFittingCategory::getPid, 0);
        lqw.eq(AiFittingCategory::getLevel, 1);
        lqw.eq(AiFittingCategory::getIsShow, 1);
        lqw.eq(AiFittingCategory::getIsDel, 0);
        lqw.orderByDesc(AiFittingCategory::getSort);
        return dao.selectList(lqw);
    }

    @Override
    public List<ProCategoryCacheVo> getSpecialTopicCacheTree() {
        List<AiFittingCategory> categoryList = CollUtil.newArrayList();
        if (redisUtil.exists(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY)) {
            categoryList = redisUtil.get(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY);
        } else {
            LambdaQueryWrapper<AiFittingCategory> lqw = Wrappers.lambdaQuery();
            lqw.eq(AiFittingCategory::getIsShow, true);
            lqw.eq(AiFittingCategory::getIsDel, false);
            categoryList = dao.selectList(lqw);
            if (CollUtil.isEmpty(categoryList)) {
                return CollUtil.newArrayList();
            }
            redisUtil.set(RedisConstants.AI_FITTING_CATEGORY_CACHE_LIST_KEY, categoryList);
        }
        List<ProCategoryCacheVo> voList = categoryList.stream().map(e -> {
            ProCategoryCacheVo cacheVo = new ProCategoryCacheVo();
            BeanUtils.copyProperties(e, cacheVo);
            return cacheVo;
        }).collect(Collectors.toList());
        ProCategoryCacheTree categoryTree = new ProCategoryCacheTree(voList);
        return categoryTree.buildTree();
    }

    /**
     * 根据三级试衣分类查询蒙版试衣图
     *
     * @param aiFittingCategoryId
     * @return
     */
    @Override
    public String getLevelMask(Integer aiFittingCategoryId) {
        AiFittingCategory threeAiFittingCategory = dao.selectById(aiFittingCategoryId);
        if (null == threeAiFittingCategory) {
            throw new CrmebException("试衣分类id不存在");
        }
        if (3 != threeAiFittingCategory.getLevel()) {
            throw new CrmebException("不是三级分类id");
        }
        //查询二级分类
        AiFittingCategory twoAiFittingCategory = dao.selectTwoLevelByThreeLevelId(threeAiFittingCategory.getPid());
        String format = StrUtil.format("{},{}", twoAiFittingCategory.getAiClothesType(), threeAiFittingCategory.getAiClothesType());
        Integer categoryId = dao.selectCategoryIdByAiFittingCategoryId(aiFittingCategoryId);
        //查询出一级分类id的名称,根据名称判断跑男模特还是女模特
        String name = dao.getNameByCategoryId(categoryId);
        Integer modelType = "男".equals(name) ? 0 : "女".equals(name) ? 1 : 2;
        UserModelUrl userModelUrl = userModelUrlService.selectByModelType(modelType);
        if (null == userModelUrl) {
            throw new CrmebException("模特类型不存在");
        }
        String maskJsonStr = userModelUrl.getMaskJsonStr();
        if (StrUtil.isBlank(maskJsonStr)) {
            throw new CrmebException("蒙版图片不存在");
        }
        List<Map<String, String>> list = (List<Map<String, String>>) JSONObject.parse(maskJsonStr);
        AtomicReference<String> image = new AtomicReference<>("");
        list.forEach(map -> {
            image.set(map.get(format));
        });
        return image.get();
    }


    private AiFittingCategory getByIdException(Integer id) {
        AiFittingCategory category = getById(id);
        if (ObjectUtil.isNull(category) || category.getIsDel()) {
            throw new CrmebException(ProductResultCode.PRODUCT_PLAT_CATEGORY_NOT_EXIST);
        }
        return category;
    }

    /**
     * 校验分类名称
     *
     * @param name 分类名称
     * @return Boolean
     */
    private Boolean checkName(String name, Integer pid) {
        LambdaQueryWrapper<AiFittingCategory> lqw = Wrappers.lambdaQuery();
        lqw.select(AiFittingCategory::getId);
        lqw.eq(AiFittingCategory::getName, name);
        lqw.eq(AiFittingCategory::getIsDel, false);
        lqw.eq(AiFittingCategory::getPid, pid);
        lqw.last(" limit 1");
        AiFittingCategory aiFittingCategory = dao.selectOne(lqw);
        return ObjectUtil.isNotNull(aiFittingCategory) ? Boolean.TRUE : Boolean.FALSE;
    }
}

